import time
import hashlib
import json
import os
import functools
from typing import Any, Dict, Optional

# 缓存存储字典
_cache_storage: Dict[str, Dict[str, Any]] = {}
# 从环境变量读取缓存过期时间，如果不存在则使用默认的4小时（秒）
def get_cache_expiry():
    try:
        expiry_str = os.getenv('CACHE_EXPIRY')
        if expiry_str:
            # 尝试将环境变量值转换为整数秒数
            return int(expiry_str)
    except (ValueError, TypeError):
        # 如果环境变量不是有效的整数，则使用默认值
        pass
    return 4 * 60 * 60  # 默认4小时

# 缓存过期时间（秒）
CACHE_EXPIRY = get_cache_expiry()


def generate_cache_key(func_name: str, **kwargs) -> str:
    """
    生成缓存键
    
    Args:
        func_name: 函数名
        **kwargs: 函数参数
    
    Returns:
        缓存键（MD5哈希值）
    """
    # 确保kwargs是可排序的，以便相同参数生成相同的键
    sorted_params = sorted(kwargs.items())
    # 创建一个包含函数名和参数的字符串
    key_string = f"{func_name}:{json.dumps(sorted_params, ensure_ascii=False)}"
    # 生成MD5哈希值作为缓存键
    return hashlib.md5(key_string.encode()).hexdigest()


def get_cached_data(key: str) -> Optional[Any]:
    """
    获取缓存数据
    
    Args:
        key: 缓存键
    
    Returns:
        缓存的数据，如果缓存不存在或已过期则返回None
    """
    if key not in _cache_storage:
        print(f"Cache miss for key: {key}")
        return None
    
    cache_item = _cache_storage[key]
    current_time = time.time()
    
    # # 每次检查时都获取最新的缓存过期时间，支持运行时调整
    # current_expiry = get_cache_expiry()
    
    # 检查缓存是否过期
    if current_time - cache_item['timestamp'] > CACHE_EXPIRY:
        # 删除过期缓存
        print(f"Cache expired for key: {key}")
        del _cache_storage[key]
        return None
    
    # 更新缓存访问时间，防止缓存因未过期却被误删
    cache_item['timestamp'] = current_time
    
    print(f"Cache hit for key: {key}")
    return cache_item['data']


def set_cached_data(key: str, data: Any) -> None:
    """
    设置缓存数据
    
    Args:
        key: 缓存键
        data: 要缓存的数据
    """
    _cache_storage[key] = {
        'data': data,
        'timestamp': time.time()
    }
    print(f"Cache set for key: {key}")


def clear_cache() -> None:
    """
    清空所有缓存
    """
    _cache_storage.clear()


def cache_decorator(func):
    """
    缓存装饰器，用于装饰API函数
    
    Args:
        func: 要装饰的函数
    
    Returns:
        装饰后的函数
    """
    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
        # 生成缓存键
        cache_key = generate_cache_key(func.__name__, **kwargs)
        
        # 尝试获取缓存数据
        cached_data = get_cached_data(cache_key)
        if cached_data is not None:
            return cached_data
        
        # 缓存未命中，执行原函数
        result = await func(*args, **kwargs)
        
        # 设置缓存
        set_cached_data(cache_key, result)
        
        return result
    
    return wrapper